package com.aokser.redisplugin.redis;

import com.aokser.redisplugin.config.BaseConfig;
import com.aokser.redisplugin.config.GenericObjectPoolConfig;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;


/**
 * 集群客户端工厂类
 * @version 1.0
 * @author aokser@foxmail.com
 */
@Component
@Lazy(true)
public class JedisClusterFactory implements FactoryBean<JedisCluster>,
        InitializingBean {

	/**
	 * JedisCluster对象
	 */
    private JedisCluster jedisCluster;
    
    /**
     * 资源池配置对象
     */
    @Autowired
    private GenericObjectPoolConfig genericObjectPoolConfig;
    
    // 服务器地址验证规则
    private Pattern pattern = Pattern.compile("^.+[:]\\d{1,5}\\s*$");

    @Override
    public void afterPropertiesSet() throws Exception {
        BaseConfig baseConfig = genericObjectPoolConfig.getBaseConfig();
        if(baseConfig.isCluster()) {
            Set<HostAndPort> haps = this.parseHostAndPort(baseConfig);  
            jedisCluster = new JedisCluster(haps, baseConfig.getTimeout(), 
                    baseConfig.getMaxRedirections(), genericObjectPoolConfig); 
        }
        
    }

    @Override
    public Class<? extends JedisCluster> getObjectType() {
        return (this.jedisCluster != null ? this.jedisCluster.getClass()
                : JedisCluster.class);
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public JedisCluster getObject() throws Exception {
        return this.jedisCluster;
    }

    /**
     * @title parseHostAndPort 
     * @description 解析主机地址及端口
     * @return Set<HostAndPort>
     * @throws
     */
    private Set<HostAndPort> parseHostAndPort(BaseConfig baseConfig) throws Exception {
        try {
            Set<HostAndPort> haps = new HashSet<HostAndPort>();
            for (String host : baseConfig.getClusterAddress()) {
                
                boolean isIpPort = pattern.matcher(host).matches();
                
                if (!isIpPort) {
                    throw new IllegalArgumentException("IP或端口不合法，请重新配置！");
                }
                
                String[] ipAndPort = host.split(":");

                HostAndPort hap = new HostAndPort(ipAndPort[0],
                        Integer.parseInt(ipAndPort[1]));
                haps.add(hap);
            }

            return haps;
        } catch (IllegalArgumentException ex) {
            throw ex;
        } catch (Exception ex) {
            throw new Exception("解析Redis配置时发生错误！", ex);
        }
    }
    
    public GenericObjectPoolConfig getGenericObjectPoolConfig() {
        return genericObjectPoolConfig;
    }

    public void setGenericObjectPoolConfig(
            GenericObjectPoolConfig genericObjectPoolConfig) {
        this.genericObjectPoolConfig = genericObjectPoolConfig;
    }

    public JedisCluster getJedisCluster() {
        return jedisCluster;
    }

    public void setJedisCluster(JedisCluster jedisCluster) {
        this.jedisCluster = jedisCluster;
    }
}
